package com.example.util;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Classname ThreadPool
 * @Description TODO
 * @Date 2023/4/25 20:59
 * @Created by XiongXiong
 * @Author: X.I.O
 */
public class ThreadPool {

    private final int nThreads; // 线程池中线程数量
    private final PoolWorker[] threads; // 线程数组
    private final BlockingQueue<Runnable> queue; // 任务阻塞队列
    private final AtomicInteger ctl = new AtomicInteger(0); // 计数器，表示正在执行或将要执行的任务数量（类似于信号量）

    /**
     * 构造方法
     *
     * @param nThreads 线程池中线程数量
     */
    public ThreadPool(int nThreads) {
        this.nThreads = nThreads;
        queue = new LinkedBlockingQueue<>();
        threads = new PoolWorker[nThreads];
        for (int i = 0; i < nThreads; i++) {
            threads[i] = new PoolWorker();
            threads[i].start();
        }
    }

    /**
     * 提交任务
     *
     * @param task 任务
     */
    public void execute(Runnable task) {
        queue.offer(task); // 先尝试放入任务到队列中
        if (ctl.incrementAndGet() <= nThreads) { // 如果当前正在执行或将要执行的任务数量小于等于线程数，那么新开一个线程执行任务
            new PoolWorker().start();
        }
    }

    /**
     * 线程工作类
     */
    private class PoolWorker extends Thread {
        public void run() {
            Runnable task;
            while ((task = queue.poll()) != null) { // 从队列中取出任务
                task.run(); // 执行任务
                ctl.decrementAndGet(); // 计数器减一
            }
        }
    }
}
